//产生随机字符串
window.GetRandomStr = function(len) {
	len = len || 32;
	var $chars = 'ABCDEFGHJKLMNOPQRSTUVWXYZabcdefhijklmnoprstuvwxyz';
	var maxPos = $chars.length;
	var pwd = '';
	for (var i = 0; i < len; i++) {
		pwd += $chars.charAt(Math.floor(Math.random() * maxPos));
	}
	return pwd;
}

Array.prototype.pushAll = function ( list , types ) {
	if ( list && ( list instanceof Array ) && list.length > 0 ) {
		for ( var i = 0 ; i < list.length ; i++ ) {
			if ( types ) {
				var isMatch = false;
				for ( var j = 0 ; j < types.length ; j++ ) {
					if ( typeof list[i] == types[j] ) {
						isMatch = true;
						break;
					}
				}
				if ( !isMatch ) {
					continue;
				}
			}
			this.push ( list[i] );
		}
	}
	return this;
};

// 定义流程画布以及数据
window.flowCanvas = function (scope, id, imageInfo, createCanvas) {

	for (var i in flowCanvasFn) {
		this[i] = flowCanvasFn[i];
	}
	this.id = id;
	this.scope = scope;
	this.imageInfo = imageInfo;
	if (!this.imageInfo.preId) {
		this.imageInfo.preId = GetRandomStr();
	}
	this.createCanvas = createCanvas; // 是否创建canvas
}

window.flowCanvasFn = {
	// 初始化
	initDraw: function () {

		this.initData();
		if (!isIE8) this.initCanvas();
		this.initDialogs();

		var flowFn = new drawFlowImg(this);
		this.imageInfo.flowFn = flowFn;

		return flowFn;
	},
	// 初始化流程图数据
	initData: function () {
		this.nodeMap = this.imageInfo.nodeMap;
		this.flowLocation = this.imageInfo.flowLocation;
		this.stacks = this.imageInfo.stacks || [];
		this.flowElements = this.imageInfo.flowElements;
		this.imageInfo.opinionMap = this.imageInfo.opinionMap || {};
		this.opinionMap = this.imageInfo.opinionMap;
		this.xoffset = this.imageInfo.xoffset || -10;
		this.yoffset = this.imageInfo.yoffset || -25;
		this.domxoffset = this.xoffset;
		this.domyoffset = this.yoffset;
		if (this.createCanvas) {
			this.xoffset = -30;
			this.yoffset = -20;

			this.domxoffset = -55;
			this.domyoffset = -50;
		}


		this.initFlowData(this.flowElements);
		this.initStatck();
		this.initNodeInfo();
		this.initNodeRelation();
		this.initNodeOpitions();
		this.initNodeType();

	},
	// 初始化画布
	initCanvas: function () {

		this.canvas = document.getElementById(this.id);
		if (this.createCanvas) {
			var canvas = $('<canvas id="' + this.id + '"></canvas>');
			this.canvas = canvas[0];
		}
		this.cxt = this.canvas.getContext('2d');
		this.ctx = this.cxt;

		// 设置画布宽高
		var minX = 10000;
		var minY = 10000;
		var maxX = 0;
		var maxY = 0;
		for (var i in this.nodeMap) {
			var xyz = this.nodeMap[i];
			minX = Math.min(minX, xyz.x);
			minY = Math.min(minY, xyz.y);
			maxX = Math.max(maxX, xyz.x + xyz.width);
			maxY = Math.max(maxY, xyz.y + xyz.height);
		}

		for (var i in this.flowLocation) {
			var flows = this.flowLocation[i];
			for (var j = 0; j < flows.length; j++) {
				var flowFrom = flows[j];
				minX = Math.min(minX, flowFrom.x);
				minY = Math.min(minY, flowFrom.y);
				maxX = Math.max(maxX, flowFrom.x + flowFrom.width);
				maxY = Math.max(maxY, flowFrom.y + flowFrom.height);
			}
		}
		this.canvas.width = maxX + minX + 300;
		this.canvas.height = maxY + minY + 200;

		// test
//	    this.canvas.width = 10000;
//	    this.canvas.height = 10000;

		// 画背景白色,否则复制出来是透明的
		this.cxt.fillStyle = "white";
		this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
	},
	initDialogs: function () {
		var setting = {
			hide: {
				event: 'mouseleave',
				leave: false,
				fixed: true,
				delay: 100
			},
			style: {
				classes: 'qtip-default  qtip qtip-bootstrap qtip-shadow'
			}
		};
		var imageInfo = this.imageInfo;
		var that = this;
		window.setTimeout(function () {
			for (var key in imageInfo.opinionMap) {
				if (!that.createCanvas) {
					setting.content = {
						text: $('#' + key)
					}
					$('#node' + key).qtip(setting);
				} else {
					// 子流程的情况
					setting.content = {
						text: $('#' + imageInfo.preId + key)
					}
					$('#subnode' + key).qtip(setting);
				}

			}
		}, 900)


	},
	// 初始化栈数据
	initStatck: function () {

		var stacks = this.stacks;
		var stackJson = {};
		var nodeTypeJson = {};
		var flowColorJson = {};
		for (var i = 0; i < stacks.length; i++) {
			var stack = stacks[i];
			stackJson[stack.nodeId] = stack;
			nodeTypeJson[stack.nodeId] = stack.nodeType;
			var actionName = stack.actionName;
			if ("sequenceFlow" == stack.nodeType) {// 线集合，线的颜色应该跟父颜色一致
				if (actionName == "create") {
					actionName = "start";
				}
			}
			flowColorJson[stack.nodeId] = this.getColor(actionName);
		}
		this.flowColorJson = flowColorJson;
		this.nodeTypeJson = nodeTypeJson;
		this.stackJson = stackJson;
	},
	// 初始化节点名称
	initNodeInfo: function () {

		var imageInfo = this.imageInfo;
		// 注释相关
		var pools = imageInfo.pools || [];
		var lanes = imageInfo.lanes || [];
		var artifacts = imageInfo.artifacts || [];
		var boundaryEvents = imageInfo.boundaryEvents || [];

		pools.pushAll(lanes);
		pools.pushAll(artifacts);
		pools.pushAll(boundaryEvents);
		var nodeNameJson = {};
		for (var i = 0; i < pools.length; i++) {
			var p = pools[i];
			if (p["$ref"]) {
				var $ = {
					data: imageInfo
				};
				p = eval("(" + p["$ref"] + ")");
			}
			nodeNameJson[p.id] = p;
		}

		this.nodeNameJson = nodeNameJson;
		var flowElementJson = this.imageInfo.flowElementJson;
		var flowColorJson = this.flowColorJson;
		var nodeMap = this.nodeMap;
		for (var i in nodeMap) {
			var xyz = nodeMap[i];
			// 绑定ID
			xyz.id = i;

			var flowElement = flowElementJson[i] || nodeNameJson[i] || flowElementJson[xyz.oldId];
			var nodeName = flowElement.name || flowElement.text;
			xyz.nodeName = nodeName;
			xyz.flowElement = flowElement;

			var color = flowColorJson[i] || this.Color.DEFAULT;
			xyz.color = color;
			xyz.domxoffset = this.domxoffset;
			xyz.domyoffset = this.domyoffset;
		}
	},
	// 级联初始化流程节点数据
	initFlowData: function (flowElements) {

		if (!flowElements) {
			return;
		}
		var imageInfo = this.imageInfo;
		var flowElementJson = imageInfo.flowElementJson || {};
		var boundaryEvents = imageInfo.boundaryEvents || [];

		for (var i = 0; i < flowElements.length; i++) {
			var flow = flowElements[i];
			flowElementJson[flow.id] = flow;

			boundaryEvents.pushAll(flow.boundaryEvents || []);
			imageInfo.boundaryEvents = boundaryEvents;
			imageInfo.flowElementJson = flowElementJson;
			var subFlowElements = flow.flowElements;
			if (subFlowElements && subFlowElements.length > 0) {
				this.initFlowData(subFlowElements)
			}
		}
	},
	// 原始的nodeType转成前端的
	nodeTypeMap: {
		BoundaryEvent: "boundaryTimer",
		IntermediateCatchEvent: "catchSignal",
		EndEvent: "endEvent",
		EndEvent1: "endEvent",
		ExclusiveGateway: "exclusiveGateway",
		ParallelGateway: "parallelGateway",
		StartEvent: "startEvent",
		ThrowEvent: "throwSignal",
		UserTask: "userTask",
		ScriptTask: "serviceTask",

		ExclusiveGateway: "exclusiveGateway",
		ParallelGateway: "parallelGateway",
		InclusiveGateway: "inclusiveGateway"
	},
	// 获取节点类型
	getNodeType: function (oldNodeType, i) {

		var nodeType = "";
		if (i.indexOf("Pool") >= 0) {
			nodeType = "pool";
		}
		if (i.indexOf("Lane") >= 0) {
			nodeType = "lane";
		}
		if (i.indexOf("StartNoneEvent") >= 0) {
			nodeType = "startEvent";
		}
		if (i.indexOf("TextAnnotation") >= 0) {
			nodeType = "textAnnotation";
		}
		if (i.indexOf("EndNoneEvent") >= 0) {
			nodeType = "endEvent";
		}
		if (i.indexOf("SubProcess") >= 0) {
			nodeType = "subProcess";
		}
		if (i.indexOf("CallActivity") >= 0) {
			nodeType = "callActivity";
		}
		if (i.indexOf("UserTask") >= 0) {
			nodeType = "userTask";
		}
		if (i.indexOf("ServiceTask") >= 0) {
			nodeType = "serviceTask";
		}
		if (i.indexOf("ExclusiveGateway") >= 0) {
			nodeType = "exclusiveGateway";
		}
		if (i.indexOf("ParallelGateway") >= 0) {
			nodeType = "parallelGateway";
		}
		if (i.indexOf("InclusiveGateway") >= 0) {
			nodeType = "inclusiveGateway";
		}

		if (i.indexOf("StartTimer") >= 0) {
			nodeType = "startTimer";
		}
		if (i.indexOf("BoundaryTimer") >= 0) {
			nodeType = "boundaryTimer";
		}
		if (i.indexOf("CatchTimer") >= 0) {
			nodeType = "catchTimer";
		}
		if (i.indexOf("StartSignal") >= 0) {
			nodeType = "startSignal";
		}
		if (i.indexOf("BoundarySignal") >= 0) {
			nodeType = "boundarySignal";
		}
		if (i.indexOf("CatchSignal") >= 0) {
			nodeType = "catchSignal";
		}
		if (i.indexOf("ThrowSignal") >= 0) {
			nodeType = "throwSignal";
		}
		if (i.indexOf("EndError") >= 0) {
			nodeType = "endError";
		}
		if (i.indexOf("BoundaryError") >= 0) {
			nodeType = "boundaryError";
		}
		if (i.indexOf("EndTerminate") >= 0) {
			nodeType = "endTerminate";
		}

		if (nodeType) {
			return nodeType;
		}

		return this.nodeTypeMap[oldNodeType] || oldNodeType;
	},

	// 获取颜色
	getColor: function (action) {

		var Color = this.Color;
		if (!action) {
			return Color.GREEN;
		}
		switch (action) {
			case "start" :
				return Color.success;
//			    return Color.DEFAULT;
			case "default" :
				return Color.DEFAULT;
			case "agree" :
				return Color.success;
			case "signAgree" :
				return Color.success;
			case "oppose" :
				return Color.PINK;
			case "signOppose" :
				return Color.PINK;
			case "reject" :
				return Color.PINK;
			case "reject2Start" :
				return Color.PINK;
			case "recover" :
				return Color.PINK;
			case "dispense" :
				return Color.BLUE;
			case "manualEnd" :
				return Color.DARK_GRAY;
			case "recall" :
				return Color.DARK_GRAY;
			case "create" :
				return Color.todo;
			case "end" :
				return Color.success;
			case "taskCancelled" :
				return Color.cancelled;
			default :
				return Color.RED;
		}
	},
	// 初始化节点类型
	initNodeType: function () {

		var nodeMap = this.imageInfo.nodeMap;
		var nodeTypeJson = this.nodeTypeJson;
		for (var i in nodeMap) {
			var xyz = nodeMap[i];
			var nodeType = xyz.type || nodeTypeJson[i];
			nodeType = this.getNodeType(nodeType, i);
			if (xyz.signTask == 1) {
				nodeType = "mutiUserTask";
			}
			if (xyz.multInst == "start") {
				nodeType = "mutiInstTaskStart";
			}

			if (xyz.multInst == "end") {
				nodeType = "mutiInstTaskEnd";
			}

			if (xyz.dynamicTask == "1") {
				nodeType = "dynamicTask";
			}

			xyz.nodeType = nodeType;
		}

	},
	// 初始化节点和意见的关系
	initNodeOpitions: function () {

		var nodeMap = this.imageInfo.nodeMap;
		var opinionMap = this.opinionMap;
		for (var i in nodeMap) {
			var opinions = opinionMap[i] || [];
			nodeMap[i].opinions = opinions;
			for (var oi = 0; oi < opinions.length; oi++) {
				opinions[oi].node = nodeMap[i];
			}
		}

	},
	// 初始化节点的前后关系
	initNodeRelation: function () {

		var imageInfo = this.imageInfo;
		if (this.createCanvas) {
			// 不需要再关联的,因为之前已经关联过了
			return;
		}
		var flowElementJson = this.imageInfo.flowElementJson;
		var flowElements = this.imageInfo.flowElements;
		var nodeMap = this.imageInfo.nodeMap;
		var flowLocation = this.flowLocation;

		var newNodeMap = {};
		var newFlowLocation = {};

		var startNodeId = flowElements[0].id;
		var startNode = flowElementJson[startNodeId];

		// 起始节点
		newNodeMap[startNodeId] = JSON.parse(JSON.stringify(nodeMap[startNodeId]));
		var hasFilterFirstLine = true;
		var startNodeMap = newNodeMap[startNodeId];
		var tempCurrentNodeMap = startNodeMap;
		var deep = 0;
		var loadedIdList = [];

		function getNextNodeAndLines(node) {

			if (loadedIdList.indexOf(node.id) >= 0) {
				return;
			}
			loadedIdList.push(node.id);

			if (deep++ > 200) {
				console.error("有问题啦,可能是无限递归");
				return;
			}

			var outgoingFlows = node.outgoingFlows || [];

			if (outgoingFlows.length == 0) {
				return;
			}

			for (var i = 0; i < outgoingFlows.length; i++) {
				var outgoingFlow = outgoingFlows[i];
				var id = outgoingFlow.id;
				if (!id) {
					var $ = {
						data: imageInfo
					};
					outgoingFlow = eval("(" + outgoingFlow.$ref + ")");
					id = outgoingFlow.id;
				}
				var outgoingFlowNode = flowElementJson[id];
				if (outgoingFlow.targetRef == node.id || outgoingFlow.targetRef == node.oldId) {
					continue;
				}
				// 判断类型
				if (!outgoingFlowNode || outgoingFlowNode.type == "SequenceFlow") {
					if (hasFilterFirstLine) {
						newFlowLocation[id] = JSON.parse(JSON.stringify(flowLocation[id]));
					} else {
						hasFilterFirstLine = true;
					}
					id = outgoingFlow.targetRef;
					outgoingFlowNode = flowElementJson[outgoingFlow.targetRef];
				}

				newNodeMap[id] = JSON.parse(JSON.stringify(nodeMap[id]));
				tempCurrentNodeMap.nextNodeMap = newNodeMap[id];
				newNodeMap[id].preNodeMap = tempCurrentNodeMap;
				tempCurrentNodeMap = newNodeMap[id];

				// 判断子流程
				var hasEndNode = false;
				if (newNodeMap[id].type == "SubProcess") {

					function getSubProcessNodes(subFlows) {

						if (!subFlows || subFlows.length == 0) {
							return;
						}
						var flowElements = subFlows;
						var subStartNodeId = flowElements[0].id;
						newNodeMap[subStartNodeId] = JSON.parse(JSON.stringify(nodeMap[subStartNodeId]));
						if (!tempCurrentNodeMap.nextNodeMap) {
							tempCurrentNodeMap.nextNodeMap = newNodeMap[subStartNodeId];
							newNodeMap[subStartNodeId].preNodeMap = tempCurrentNodeMap;
							tempCurrentNodeMap = newNodeMap[subStartNodeId];
						}

						for (var k = 0; k < flowElements.length; k++) {
							if (flowElements[k].id) {
								var subId = flowElements[k].id;
								var isSub = nodeMap[subId].type == "SubProcess";
								// 由于多层的子流程中后端没有返回类型,所以还需要再判断一次
								if (!isSub && !nodeMap[subId].type && subId.indexOf("SubProcess") >= 0) {
									isSub = true;
								}

								if (isSub) {
									getSubProcessNodes(flowElements[k].flowElements);
								}

								getNextNodeAndLines(flowElements[k]);

							}
						}
					}

					getSubProcessNodes(outgoingFlowNode.flowElements);
				}

				// 判断是否是结束节点
				getNextNodeAndLines(outgoingFlowNode);
			}
		}

		getNextNodeAndLines(startNode);

		for (var i in imageInfo.nodeMap) {
			if (newNodeMap[i]) {
				imageInfo.nodeMap[i] = newNodeMap[i];
			}
		}
		imageInfo.flowLocation = newFlowLocation;

	},
	// 获取两个节点间的流程信息 [镜像的]
	getFLowImageInfo: function (startNodeId, endNodeId) {

		var imageInfo = this.imageInfo;
		var flowElementJson = this.imageInfo.flowElementJson;
		var nodeMap = this.imageInfo.nodeMap;
		var flowLocation = this.flowLocation;

		if (!nodeMap[startNodeId]) {
			//
			var hasNode = false;
			for (var i in nodeMap) {
				if (nodeMap[i].oldId == startNodeId) {
					hasNode = true;
					startNodeId = nodeMap[i].id;
					break;
				}
			}
			if (!hasNode) {
				console.error("找不到开始节点信息:" + startNodeId);
				return;
			}
		}

		if (!nodeMap[endNodeId]) {
			console.error("找不到结束节点信息:" + endNodeId);
			return;
		}

		var newNodeMap = {};
		var newFlowLocation = {};

		var startNode = flowElementJson[startNodeId];

		// 起始节点
		newNodeMap[startNodeId] = JSON.parse(JSON.stringify(nodeMap[startNodeId]));

		newNodeMap[startNodeId].type = 'StartEvent';
		startNode.type = 'StartEvent';
		newNodeMap[startNodeId].icon = 'mutiInstIcon';
		newNodeMap[startNodeId].reg = -90;

		var tempStartNodeId = 'StartNoneEvent_muti';

		startNode.id = tempStartNodeId;
		newNodeMap[startNodeId].id = tempStartNodeId;
		newNodeMap[tempStartNodeId] = newNodeMap[startNodeId];

		// 将第一个节点改成一个圈圈
		var startNodeMap = newNodeMap[tempStartNodeId];
		startNodeMap.multInst = "";
		startNodeMap.multInst_end = "";
		startNodeMap.oldId = startNodeId;

		var oldW = startNodeMap.width;
		var oldH = startNodeMap.height;
		startNodeMap.width = 30;
		startNodeMap.height = 30;
		startNodeMap.x = startNodeMap.x + oldW / 2 + 20;
		startNodeMap.y = startNodeMap.y + oldH / 2 + this.yoffset;

		startNode.oldId = startNodeId;
		delete newNodeMap[startNodeId]

		var hasFilterFirstLine = true;
		var isFirstLine = false;

		function getNextNodeAndLines(node) {

			var outgoingFlows = node.outgoingFlows || [];
			// 判断目标节点是否含有最终节点
			var hasEnd = false;
			for (var i = 0; i < outgoingFlows.length; i++) {
				var outgoingFlow = outgoingFlows[i];
				var id = outgoingFlow.id;
				var outgoingFlowNode = flowElementJson[id];
				if (outgoingFlow.targetRef == endNodeId) {
					hasEnd = true;
					break;
				}
			}
			for (var i = 0; i < outgoingFlows.length; i++) {
				var outgoingFlow = outgoingFlows[i];
				var id = outgoingFlow.id;
				if (!id) {
					var $ = {
						data: imageInfo
					};
					outgoingFlow = eval("(" + outgoingFlow.$ref + ")");
					id = outgoingFlow.id;
				}
				var outgoingFlowNode = flowElementJson[id];
				if (outgoingFlow.targetRef == node.id || outgoingFlow.targetRef == node.oldId || (hasEnd && outgoingFlow.targetRef != endNodeId)) {
					continue;
				}
				// 判断类型
				if (!outgoingFlowNode || outgoingFlowNode.type == "SequenceFlow") {
					if (!isFirstLine) {
						isFirstLine = true;
						// 设置第一个节点的坐标
						startNodeMap.x = flowLocation[id][0].x - startNodeMap.width + 3;
						startNodeMap.y = flowLocation[id][0].y - startNodeMap.height + 3;
					}

					if (hasFilterFirstLine) {
						newFlowLocation[id] = JSON.parse(JSON.stringify(flowLocation[id]));
					} else {
						hasFilterFirstLine = true;
					}
					id = outgoingFlow.targetRef;
					outgoingFlowNode = flowElementJson[outgoingFlow.targetRef];
				}

				newNodeMap[id] = JSON.parse(JSON.stringify(nodeMap[id]));
				// 判断子流程
				var hasEndNode = false;
				if (newNodeMap[id].type == "SubProcess") {

					function getSubProcessNodes(subFlows) {

						if (!subFlows || subFlows.length == 0) {
							return;
						}
						var flowElements = subFlows;
						var subStartNodeId = flowElements[0].id;
						newNodeMap[subStartNodeId] = JSON.parse(JSON.stringify(nodeMap[subStartNodeId]));

						for (var k = 0; k < flowElements.length; k++) {
							if (flowElements[k].id) {
								var subId = flowElements[k].id;
								var isSub = nodeMap[subId].type == "SubProcess";
								// 由于多层的子流程中后端没有返回类型,所以还需要再判断一次
								if (!isSub && !nodeMap[subId].type && subId.indexOf("SubProcess") >= 0) {
									isSub = true;
								}

								if (subId == endNodeId) {
									hasEndNode = true;
									return hasEndNode;
								}

								if (isSub) {
									var isEnd = getSubProcessNodes(flowElements[k].flowElements);
									if (isEnd) {
										return true;
									}
								}

								getNextNodeAndLines(flowElements[k]);

							}
						}
					}

					getSubProcessNodes(outgoingFlowNode.flowElements);
				}

				// 判断是否是结束节点
				if (id != endNodeId && !hasEndNode) {
					getNextNodeAndLines(outgoingFlowNode);
				}
			}
		}

		getNextNodeAndLines(startNode);
		var imageInfo = {};

		for (var i in this.imageInfo) {
			if (i != 'flowFn') {
				imageInfo[i] = JSON.parse(JSON.stringify(this.imageInfo[i]));
			}
		}

		imageInfo.nodeMap = newNodeMap;
		imageInfo.flowLocation = newFlowLocation;
		imageInfo.startNodeId = tempStartNodeId;
		imageInfo.flowElementJson = flowElementJson;


		return imageInfo;

	},
	Point: function (x, y) {

		return {
			x: x,
			y: y
		};
	},
	Rect: function (x, y, w, h) {

		return {
			x: x,
			y: y,
			w: w,
			h: h,
			width: w,
			height: h
		};
	},
	Color: {
		GREEN: "rgb(0, 255, 0)",
		success: "rgb(26, 179, 148)",
		PINK: "rgb(255, 153, 0)",
		BLUE: "rgb(0, 0, 255)",
		DARK_GRAY: "rgb(64, 64, 64)",
		todo: "rgb(237, 85, 101)",
		cancelled: "rgb(28, 132, 198)",
		RED: "rgb(255, 0, 0)",
		DEFAULT: "rgb(103, 106, 108)",
	},
	closeFlow: function () {
		// 超过多层
		if (!window.hisSubFlow || window.hisSubFlow.length == 0) {
			return
		}

		if (window.hisSubFlow.length > 1) {
			var parentFlow = window.hisSubFlow[window.hisSubFlow.length - 2]
			// 打开上一层流程
			var scope = parentFlow.scope;
			scope.openCallActivity(parentFlow.node, parentFlow.subInst, parentFlow.type);
			window.hisSubFlow.splice(window.hisSubFlow.length - 1, 1);
		}
		window.hisSubFlow.splice(window.hisSubFlow.length - 1, 1);
	}
}

